#ifndef P2P_BASE_TRANSPORTCHANNEL_H_
#define P2P_BASE_TRANSPORTCHANNEL_H_

#include <vector>
#include "base/sigslot.h"
#include "base/socket.h"

namespace cricket
{
	// Flags for SendPacket/SignalReadPacket
	enum PacketFlags
	{
		PF_NORMAL       = 0x00,  // A normal packet.
		PF_SRTP_BYPASS  = 0x01,  // An encrypted SRTP packet; bypass any additional
								 // crypto provided by the transport (e.g. DTLS)
	};

	// A TransportChannel represents one logical stream of packets that are sent
	// between the two sides of a session.
	class TransportChannel : public sigslot::has_slots<>
	{
	public:
		explicit TransportChannel(const std::string& content_name, int component)
			: content_name_(content_name),
			component_(component),
			readable_(false), writable_(false) {}
		virtual ~TransportChannel() {}

		// Returns the session id of this channel.
		virtual const std::string& SessionId() const { return session_id_; }
		// Sets session id which created this transport channel.
		// This is called from TransportProxy::GetOrCreateImpl.
		virtual void SetSessionId(const std::string& session_id) {
			session_id_ = session_id;
		}
		const std::string& content_name() const { return content_name_; }
		int component() const { return component_; }

		// Returns the readable and states of this channel.  Each time one of these
		// states changes, a signal is raised.  These states are aggregated by the
		// TransportManager.
		bool readable() const { return readable_; }
		bool writable() const { return writable_; }
		sigslot::signal1<TransportChannel*> SignalReadableState;
		sigslot::signal1<TransportChannel*> SignalWritableState;
		// Emitted when the TransportChannel's ability to send has changed.
		sigslot::signal1<TransportChannel*> SignalReadyToSend;

		// Attempts to send the given packet.  The return value is < 0 on failure.
		// TODO: Remove the default argument once channel code is updated.
		virtual int SendPacket(const char* data, size_t len, int flags = 0) = 0;

		// Sets a socket option on this channel.  Note that not all options are
		// supported by all transport types.
		virtual int SetOption(base::Socket::Option opt, int value) = 0;

		// Returns the most recent error that occurred on this channel.
		virtual int GetError() = 0;

		// Returns current transport channel ICE role.
		virtual TransportRole GetRole() const = 0;

		// Returns the current stats for this connection.
		virtual bool GetStats(ConnectionInfos* infos) {
			return false;
		}

		// Is DTLS active?
		virtual bool IsDtlsActive() const {
			return false;
		}

		// Set up the ciphers to use for DTLS-SRTP.
		virtual bool SetSrtpCiphers(const std::vector<std::string>& ciphers) {
			return false;
		}

		// Find out which DTLS-SRTP cipher was negotiated
		virtual bool GetSrtpCipher(std::string* cipher) {
			return false;
		}

		// Allows key material to be extracted for external encryption.
		virtual bool ExportKeyingMaterial(const std::string& label,
			const uint8* context,
			size_t context_len,
			bool use_context,
			uint8* result,
			size_t result_len) {
				return false;
		}

		// Signaled each time a packet is received on this channel.
		sigslot::signal4<TransportChannel*, const char*,
			size_t, int> SignalReadPacket;

		// This signal occurs when there is a change in the way that packets are
		// being routed, i.e. to a different remote location. The candidate
		// indicates where and how we are currently sending media.
		sigslot::signal2<TransportChannel*, const Candidate&> SignalRouteChange;

		// Invoked when the channel is being destroyed.
		sigslot::signal1<TransportChannel*> SignalDestroyed;

		// Debugging description of this transport channel.
		std::string ToString() const;

	protected:
		// Sets the readable state, signaling if necessary.
		void set_readable(bool readable);

		// Sets the writable state, signaling if necessary.
		void set_writable(bool writable);

	private:
		std::string session_id_;
		// Used mostly for debugging
		std::string content_name_;
		int component_;
		bool readable_;
		bool writable_;

		DISALLOW_EVIL_CONSTRUCTORS(TransportChannel);
	};
}

#endif	// P2P_BASE_TRANSPORTCHANNEL_H_